package cn.com.yusys.yusp.admin.service;

import cn.com.yusys.yusp.admin.Utils.*;
import cn.com.yusys.yusp.admin.domain.AcrmGridInfo;
import cn.com.yusys.yusp.admin.repository.mapper.GridGeneralMapper;
import cn.com.yusys.yusp.commons.mapper.CommonMapper;
import cn.com.yusys.yusp.commons.mapper.QueryModel;
import cn.com.yusys.yusp.commons.service.CommonService;
import cn.com.yusys.yusp.commons.util.DateUtil;
import com.github.pagehelper.PageHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.sql.Clob;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @version 1.0.0
 * @项目名称: yusp-admin
 * @类名称: SystemLogService
 * @类描述: 网格概览业务
 * @功能描述:
 * @创建人: wcq
 * @创建时间: 2021-5-26
 * @修改备注:
 * @修改记录: 修改时间    修改人员    修改原因
 * -------------------------------------------------------------
 * @Copyright (c) 2017宇信科技-版权所有
 */
@Service
public class GridGeneralService extends CommonService {
    private static Logger logger = LoggerFactory.getLogger(GridGeneralService.class);
    @Autowired
    private GridGeneralMapper mapper;

    @Autowired
    private UserProviderService providerService;
    /**
     * @方法名称: queryOneLevel
     * @方法描述:
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryOneLevel(QueryModel model) {
        List<Map<String, Object>> maps = null;
        if("3".equals(model.getCondition().get("level"))){
            //查找客户经理的二级网格和上级网格
            maps = mapper.queryTwoLevelAndUp(model);
        }else{
            maps = mapper.queryOneLevel(model);
        }
        return map2MapStirng(maps);
    }

    /**
     * @方法名称: queryTwoLevel
     * @方法描述:
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryTwoLevel(QueryModel model) {
        List<Map<String, Object>> maps = mapper.queryTwoLevel(model);
        return map2MapStirng(maps);
    }

    /**
     * @方法名称: queryThirdLevel
     * @方法描述:
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryThirdLevel(QueryModel model) {
        List<Map<String, Object>> maps = mapper.queryThirdLevel(model);
        return map2MapStirng(maps);
    }

    /**
     * @方法名称: queryOnlyOneLevel
     * @方法描述: 仅查一级网格
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryOnlyOneLevel(QueryModel model) {
        List<Map<String, Object>> maps = mapper.queryOnlyOneLevel(model);
        return map2MapStirng(maps);
    }

    /**
     * @方法名称: queryOneLevelByOrgId
     * @方法描述: 机构ID查询一级网格及该网格下的二级网格
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryOneLevelByOrgId(QueryModel model) {
        List<Map<String, Object>> maps = mapper.queryOneLevelByOrgId(model);
        return map2MapStirng(maps);
    }

    /**
     * @方法名称: queryTwoLevelGridByUserId
     * @方法描述: 用户ID查询二级网格及该网格下的三级建筑物点
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryTwoLevelGridByUserId(QueryModel model) {
        List<Map<String, Object>> maps = mapper.queryTwoLevelGridByUserId(model);
        return map2MapStirng(maps);
    }

    /**
     * @方法名称: checkGripOnPolygon
     * @方法描述: 取第一个点去后台判断是哪个网格内的二级网格，取出上级网格ID，并写入到上级网格中去 要区分客户经理和支行、行长
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> checkGripOnPolygon(QueryModel model) {
        String level = model.getCondition().get("level").toString();
        List<Map<String, Object>> maps = null;

        if ("1".equals(level)) {
            //支行和行长：查询支行网格所有1级网格，遍历check点是否在网格内，在则返回1级网格ID和网格名称
            maps = mapper.queryOnlyOneLevelByOrgId(model);
        } else {
            //客户经理：查询此客户经理的二级网格，遍历check点是否在网格内，在则返回二级级网格ID和网格名称
            maps = mapper.queryOnlyTwoLevelByUserId(model);
        }
        //遍历check点是否在网格内，在则返回网格ID和网格名称
        return checkMap2MapStirng(Double.valueOf(model.getCondition().get("lon").toString()),Double.valueOf(model.getCondition().get("lat").toString()),maps);
    }

    /**
     * @方法名称: saveGridData
     * @方法描述: 一二级网格新建信息保存
     * @参数与返回说明:
     * @算法描述:
     */
    public Integer saveGridData(Map map) {
        AcrmGridInfo acrmGridInfo = new AcrmGridInfo();
//        map.put("createUser",providerService.getUserCode());
//        map.put("createTime", DateUtil.formatDateTimeByDef());
        String guid = IDUtils.getGuid();
        acrmGridInfo.setTableId(guid);
        acrmGridInfo.setLongitude(map.get("longitude").toString().trim());
        acrmGridInfo.setLatitude(map.get("latitude").toString().trim());
        acrmGridInfo.setGridLevel(map.get("gridLevel").toString());
        acrmGridInfo.setCreateUserName(map.get("userName").toString());
        acrmGridInfo.setCreateUser(providerService.getUserCode());
        acrmGridInfo.setCreateTime(DateUtil.formatDateTimeByDef());
        if("1".equals(map.get("gridLevel").toString())){
            List<Map<String, Object>> maps = mapper.selectOneLevelExist(map);
            if (maps.size()>0){
                acrmGridInfo.setId(maps.get(0).get("id").toString());
            }else{
                acrmGridInfo.setId(guid);
            }
            acrmGridInfo.setGridSceneType("");
            acrmGridInfo.setSectionId(map.get("sectionid").toString());
        }else{
//            if (maps.size()>0){
//                acrmGridInfo.setPregrid(maps.get(0).get("id").toString());
//            }else{
                acrmGridInfo.setId(guid);
//            }
            acrmGridInfo.setSectionId("");
        }
        acrmGridInfo.setOrgId(map.get("orgId").toString());

        acrmGridInfo.setPregrid(map.get("upGridId").toString());

        if("3".equals(map.get("gridLevel").toString())){
            acrmGridInfo.setGridName(map.get("buildName").toString());
            acrmGridInfo.setGridSceneType(map.get("scenePro").toString());
        }else if("1".equals(map.get("gridLevel").toString())){
            acrmGridInfo.setGridName(map.get("gridName").toString());
        } else{
            acrmGridInfo.setGridName(map.get("gridName").toString());
            acrmGridInfo.setGridSceneType(map.get("gridType").toString());
            //3级建筑物点需进行WCRM_GRID_UNIT_INFO的插入
            HashMap<String, Object> map1 = new HashMap<>();
            map1.put("id",guid);
            map1.put("gridId",guid);
            map1.put("preGrid",map.get("upGridId").toString());
            map1.put("unitType",map.get("gridType").toString());
            map1.put("unitName",map.get("gridName").toString());
            map1.put("createUserName",map.get("userName").toString());
            map1.put("createUser",providerService.getUserCode());
            map1.put("createTime",DateUtil.formatDateTimeByDef());

            int i = mapper.insertGridData2Unit(map1);
        }

        int i = mapper.insertGridData(acrmGridInfo);
        return i;
    }

    public List<Map<String, Object>> checkMap2MapStirng(double pointLon, double pointLat, List<Map<String, Object>> maps) {
        List<Map<String, Object>> listMap = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        maps.stream().forEach(item -> {
            try {
                String latitude = Clob2StringUtils.ClobToString((Clob) item.get("latitude"));
                String longitude = Clob2StringUtils.ClobToString((Clob) item.get("longitude"));
                List<Double> collectLat = Arrays.stream(latitude.split(",")).map(Double::parseDouble).collect(Collectors.toList());
                List<Double> collectLon = Arrays.stream(longitude.split(",")).map(Double::parseDouble).collect(Collectors.toList());
                Double[] doubleLon = new Double[collectLon.size()];
                Double[] doubleLat = new Double[collectLat.size()];
                for (int i = 0; i < collectLat.size(); i++) {
                    doubleLat[i] = collectLat.get(i);
                    doubleLon[i] = collectLon.get(i);
                }
                boolean inPolygon = RegionUtil.isInPolygon(pointLon, pointLat, doubleLon, doubleLat);
                if(inPolygon){
                    map.put("id",item.get("id"));
                    map.put("gridName",item.get("gridname"));
                    listMap.add(map);
                    return;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        return listMap;
    }

    //Map value clob -> Map value String
    public List<Map<String, Object>> map2MapStirng(List<Map<String, Object>> maps) {
        Map<String, String> markLatitude = new HashMap<>();
        Map<String, String> markLongitude = new HashMap<>();
        maps.stream().forEach(item -> {
            try {
                markLatitude.put((String) item.get("tableId"), Clob2StringUtils.ClobToString((Clob) item.get("latitude")));
                markLongitude.put((String) item.get("tableId"), Clob2StringUtils.ClobToString((Clob) item.get("longitude")));
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        for (int i = 0; i < maps.size(); i++) {
            for (Map.Entry<String, String> entry : markLatitude.entrySet()) {
                if (entry.getKey().equals(maps.get(i).get("tableId").toString())) {
                    maps.get(i).put("latitude", entry.getValue());
                }
            }
            for (Map.Entry<String, String> entry1 : markLongitude.entrySet()) {
                if (entry1.getKey().equals(maps.get(i).get("tableId").toString())) {
                    maps.get(i).put("longitude", entry1.getValue());
                }
            }
        }
        return maps;
    }

    @Override
    protected CommonMapper<?> getMapper() {
        return mapper;
    }


    /**
     * @方法名称: queryOnlyOneLevelModify
     * @方法描述: 仅查一级网格--网格·名称选择
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryOnlyOneLevelModify(QueryModel model) {
        List<Map<String, Object>> maps = mapper.queryOnlyOneLevelModify(model);
        return maps;
    }
    /**
     * @方法名称: querySecByGridName
     * @方法描述: 根据网格Name查询网格备注
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> querySecByGridName(QueryModel model) {
        List<Map<String, Object>> maps = mapper.querySecByGridName(model);
        return maps;
    }
    /**
     * @方法名称: queryModifyPolygon
     * @方法描述: 根据选择内容定位gridId
     * 此方法需根据  ->总行取全部1级网格及选择网格可修改  ->支行进行去起机构的全部二级网格，且选择的可修改
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryModifyPolygon(QueryModel model) {
        String level = model.getCondition().get("level").toString();
        List<Map<String, Object>> maps = null;
        List<Map<String, Object>> needModifyPolygon = null;
        if ("1".equals(level)) {
            needModifyPolygon =mapper.queryModifyPolygon(model);
            maps = mapper.queryOnlyOneModifyPolygon(model);
        } else {
            needModifyPolygon =mapper.queryTwoModifyPolygon(model);
            maps = mapper.queryOnlyTwoLevelGridModify(model);
        }
        return dealMapMark(maps,needModifyPolygon);
    }

    public List<Map<String, Object>> dealMapMark(List<Map<String, Object>> maps,List<Map<String, Object>> needModifyPolygon){
        List<Map<String, Object>> newList = new ArrayList<Map<String, Object>>();
        maps.stream().forEach(item -> {
            if(item.get("tableId").toString().equals(needModifyPolygon.get(0).get("tableId").toString())){
                item.put("modify","1");
            }
            newList.add(item);
        });
        return map2MapStirng(newList);
    }
    /**
     * @方法名称: updataPolygonInfo
     * @方法描述: 保存网格修改信息
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Integer updataPolygonInfo(Map map) {
        int i = mapper.updataPolygonInfo(map);
        return i;
    }

    /**
     * @方法名称: queryOnlyTwoLevelGridModify
     * @方法描述: 机构ID查询该网格下的二级网格
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public List<Map<String, Object>> queryOnlyTwoLevelGridModify(QueryModel queryModel) {
        List<Map<String, Object>> maps = mapper.queryOnlyTwoLevelGridModify(queryModel);
        return map2MapStirng(maps);
    }

    public Object selectGridTableList(QueryModel model) {
        PageHelper.startPage(model.getPage(), model.getSize());
        List<Map<String, Object>> list = null;
        if("1".equals(model.getCondition().get("roleLevel"))){//总行管理 查看全部 1级网格
            list = mapper.selectGridTableListRoleLevel1(model);
        }else if("2".equals(model.getCondition().get("roleLevel"))){//支行查看本支行所有的2级网格可做修改 补齐房价户数等信息
            list = mapper.selectGridTableListRoleLevel2(model);
        }else{//客户经理查看分配给自己的网格信息，可进行网格关键人信息，建筑物信息的补齐
            list = mapper.selectGridTableListRoleLevel3(model);
        }
        PageHelper.clearPage();
        return map2MapStirng(list);
    }
    /**
     * @方法名称: queryGridInfoById
     * @方法描述: 根据网格id查询网格基本信息
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Object queryGridInfoById(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryGridInfoById(queryModel);
        return map2MapStirng(list);
    }

    /**
     * @方法名称: queryGridKeyManById
     * @方法描述: 根据网格id查询关键人信息
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Object queryGridKeyManById(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryGridKeyManById(queryModel);
        return list;
    }

    /**
     * @方法名称: updateGridInfoById
     * @方法描述: 更新网格信息
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Object updateGridInfoById(Map map) {
        List<Map<String, Object>> list = mapper.selectGridDetailById(map);
        int i = 0;
        if(list.size()>0){
            map.put("lastUpdateUser",providerService.getUserCode());
            map.put("lastUpdateTime", DateUtil.formatDateTimeByDef());
            mapper.updateGridInfoById(map);
        }else{
            map.put("tableId",IDUtils.getGuid());
            map.put("createUser",providerService.getUserCode());
            map.put("createTime", DateUtil.formatDateTimeByDef());
            i = mapper.insertGridInfoById(map);
        }
        return i;
    }

    /**
     * @方法名称: queryGridKeyManById
     * @方法描述: 根据网格id查询建筑物信息
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Object queryGridBuildById(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryGridBuildById(queryModel);
        return list;
    }
    /**
     * @方法名称: saveKeyManGridData
     * @方法描述: 保存关键人信息
     * @参数与返回说明:
     * @算法描述:
     */
    public Integer saveKeyManGridData(Map map) {
        int i = 0;
        if(map.get("id") == null || "".equals(map.get("id"))){
            map.put("id",IDUtils.getGuid());
            map.put("createUser",providerService.getUserCode());
            map.put("createTime", DateUtil.formatDateTimeByDef());
            i = mapper.insertKeyManGridData(map);
        }else{
            map.put("lastUpdateUser",providerService.getUserCode());
            map.put("lastUpdateTime", DateUtil.formatDateTimeByDef());
            i = mapper.updateKeyManGridData(map);
        }
        return i;
    }

    /**
     * 批量删除关键人的业务逻辑
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Result<String> deleteBatch(String ids) {
        if (StringUtils.isEmpty(ids)) return ResultUtils.error("参数不能为空");
        try {
//            String[] idStr = ids.toString().split(",");
//            for (int i = 0; i < idStr.length; i++) {
//                if (!"".equals(idStr[i])) {
            mapper.deleteById(ids);
//                }
//            }
            return ResultUtils.success("数据删除成功");
        } catch (Exception e) {
            logger.info(e.getMessage(), e);
            return ResultUtils.error("系统错误, 请联系管理员");
        }
    }

    /**
     * @方法名称: saveBuildInfoGridData
     * @方法描述: 保存建筑物信息
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Result<String> saveBuildInfoGridData(Map map) {
        Result<String> r = null;
        if(map.get("id") == null || "".equals(map.get("id"))){
            r = ResultUtils.error("修改失败，未找到对应建筑物");
        }else{
            map.put("lastUpdateUser",providerService.getUserCode());
            map.put("lastUpdateTime", DateUtil.formatDateTimeByDef());
            mapper.updateBuildInfoGridData(map);
            r = ResultUtils.success("建筑物信息修改成功");
        }
        return r;
    }

    /**
     * 批量删除建筑物的业务逻辑
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Result<String> deletebatchBuild(String ids) {
        if (StringUtils.isEmpty(ids)) return ResultUtils.error("参数不能为空");
        try {
            mapper.deleteBuildById(ids);
            //删除WCRM_GRID_INFO表对应的建筑物
            mapper.deleteBuildInGridInfoById(ids);
            return ResultUtils.success("数据删除成功");
        } catch (Exception e) {
            logger.info(e.getMessage(), e);
            return ResultUtils.error("系统错误, 请联系管理员");
        }
    }


    /**
     * @方法名称: saveMgrFPGridData
     * @方法描述: 保存客户经理分配信息  1、第一次分配保存到user_info 第二次分配update  user_info并增加grid_transfer表,增量
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Integer saveMgrFPGridData(Map map) {
        List<Map<String, Object>> list = mapper.selectGridUserFPById(map);
        int i = 0;
        int j = 0;
        map.put("id",IDUtils.getGuid());
        if(list.size()>0){
            map.put("lastUpdateUser",providerService.getUserCode());
            map.put("lastUpdateTime", DateUtil.formatDateTimeByDef());
            i = mapper.updateGridUserFP(map);
            j = mapper.insertGridTransfer(map);
        }else{
            map.put("createUser",providerService.getUserCode());
            map.put("createTime", DateUtil.formatDateTimeByDef());
            i = mapper.insertGridUserFP(map);
        }
        return i+j;
    }

    /**
     * @方法名称: queryGridBuildById
     * @方法描述: 根据网格id和等级查询网格详情
     * @参数与返回说明:
     * @算法描述:
     */
    @Transactional(readOnly = true)
    public Object queryOneLevelGridInfo(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryOneLevelGridInfo(queryModel);
        return list;
    }

    @Transactional(readOnly = true)
    public Object queryOneLevelGridInfoCustNum(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryOneLevelGridInfoCustNum(queryModel);
        return list;
    }

    @Transactional(readOnly = true)
    public Object queryOneLevelGridInfoCustNumChange(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryOneLevelGridInfoCustNumChange(queryModel);
        return list;
    }

    @Transactional(readOnly = true)
    public Object queryTwoLevelGridInfo(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryTwoLevelGridInfo(queryModel);
        return list;
    }

    @Transactional(readOnly = true)
    public Object queryTwoLevelGridInfoCustNum(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryTwoLevelGridInfoCustNum(queryModel);
        return list;
    }

    @Transactional(readOnly = true)
    public Object queryTwoLevelGridInfoCustNumChange(QueryModel queryModel) {
        List<Map<String, Object>> list = mapper.queryTwoLevelGridInfoCustNumChange(queryModel);
        return list;
    }
}